package java8;

import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

import org.junit.Test;

public class FunctionalInterface_Tester {

	@FunctionalInterface
	public interface Handler<O> {// like Consumer
		void handle(O obj);
	}

	public <O> void consume(final Handler<O> handler, final O obj) { handler.handle(obj); }

	@FunctionalInterface
	public interface Converter<Source, Target> {// like Function
		Target convert(Source source);
	}

	public <Source, Target> Target function(final Converter<Source, Target> converter, final Source source) { return converter.convert(source); }

	@Test
	public void test() {
		this.consume(param -> { System.out.println(param); }, "str");
		String result = this.function(param -> { return param + " world"; }, "hello");
		System.out.println(result);
	}

	// examples

	// 不接收参数
	public <T> T useSupplier(final Supplier<T> fi) { return fi.get(); }// 生产者：返回指定类型。

	// 接收1个参数
	public <T> void useConsumer(final Consumer<T> fi, final T t) { fi.accept(t); }// 消费者：void返回值。
	public <T, R> R useFunction(final Function<T, R> fi, final T t) { return fi.apply(t); }// 函数（转换器）：不同类型返回值。
	public <T> boolean usePredicate(final Predicate<T> fi, final T t) { return fi.test(t); }// 断言（验证器）：boolean返回值。
	public <T> T useUnaryOperator(final UnaryOperator<T> fi, final T t) { return fi.apply(t); }// 一元操作（处理器）：相同类型返回值。

	// 接收2个参数
	public <T, U> void useBiConsumer(final BiConsumer<T, U> fi, final T t, final U u) { fi.accept(t, u); }// 消费者：void返回值。
	public <T, U, R> R useFunction(final BiFunction<T, U, R> fi, final T t, final U u) { return fi.apply(t, u); }// 函数（转换器）：不同类型返回值。
	public <T, U> boolean usePredicate(final BiPredicate<T, U> fi, final T t, final U u) { return fi.test(t, u); }// 断言（验证器）：boolean返回值。
	public <T> T useUnaryOperator(final BinaryOperator<T> fi, final T t, final T t2) { return fi.apply(t, t2); }// 二元操作（处理器）：相同类型返回值。

}
